package com.excel.validators.core.extension;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

import com.excel.validators.core.extension.annotation.AuditMetaData;
import com.excel.validators.core.extension.annotation.BaseNode;
import com.excel.validators.core.extension.annotation.DateNode;
import com.excel.validators.core.extension.annotation.DecimalNode;
import com.excel.validators.core.extension.annotation.InnerModel;
import com.excel.validators.core.extension.annotation.InnerSummary;

/**
 * @author wangxiaoliang10
 *
 * 2017年8月5日
 */
final class CoreSupport {

	private ClassReader cr;
	
	private ClassWriter cw;
	
	private MakeInstall handler;
	
	private byte[] code;
	
	public CoreSupport() {
			super();
			this.handler = new MakeInstall();
			this.cr = new ClassReader(handler.getResourceBytes());
			this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
	}
	
	/**
	 * 编译注解
	 * @param names
	 * @param cellIndexs
	 */
	protected void make(InnerSummary metadatas) {
			// TODO 创建 InnerSummary
			AnnotationVisitor summary = 
						cw.visitAnnotation(
								"Lcom/excel/validators/core/extension/annotation/InnerSummary;", true);
			AnnotationVisitor models = summary.visitArray("excelModels");
			
			for (InnerModel em : metadatas.excelModels()) {
					// TODO 创建 InnerModel
					AnnotationVisitor InnerModels = models.visitAnnotation(null, 
							"Lcom/excel/validators/core/extension/annotation/InnerModel;");
					// TODO InnerModel添加namespace
					InnerModels.visit("namespace", em.namespace());
					InnerModels.visit("clspath", em.clspath());
					InnerModels.visit("validator", em.validator() != null ? em.validator() : "");
					// TODO 创建 AuditMetaData
					AnnotationVisitor metadata = InnerModels.visitArray("auditMetaDatas");
					// create auditMetadata annotation start
					for (AuditMetaData md : em.auditMetaDatas()) {
							AnnotationVisitor audit = metadata.visitAnnotation(null, 
									"Lcom/excel/validators/core/extension/annotation/AuditMetaData;");
							audit.visit("name", md.name());
							audit.visit("column", md.column() != null ? md.column() : md.name());
							audit.visit("index", md.index());
							// create base annotation
							BaseNode baseNode = md.base();
							AnnotationVisitor base = audit.visitAnnotation("base", 
									"Lcom/excel/validators/core/extension/annotation/BaseNode;");
							base.visit("type", baseNode.type());
							
							DateNode dateNode = baseNode.dateNode();
							DecimalNode decimal = baseNode.decimal();
							if (dateNode != null) {
									AnnotationVisitor date = base.visitAnnotation("dateNode", 
											"Lcom/excel/validators/core/extension/annotation/DateNode;");
									date.visit("pattern", dateNode.pattern());
									date.visitEnd();
							}
							if (decimal != null) {
									AnnotationVisitor bigDecimal = base.visitAnnotation("decimal", 
											"Lcom/excel/validators/core/extension/annotation/DecimalNode;");
									bigDecimal.visit("decimal", decimal.decimal());
									bigDecimal.visitEnd();
							}
							// base create end
							base.visitEnd();
							// create auditMetadata end
							audit.visitEnd();
					}
					metadata.visitEnd();
					InnerModels.visitEnd();
			}
			models.visitEnd();
			summary.visitEnd();
			complete();
	}

	/**
	 * 结束编译，生成字节码
	 */
	protected void complete() {
			cr.accept(new ClassVisitor(Opcodes.ASM5,cw) {
					@Override
					public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
							return null;
					}
			}, 0);
			this.code = cw.toByteArray();
	}
	
	/**
	 * 替换class文件
	 */
	protected void install() {
			handler.write(getCode());
			// Invalid for initial update ,so that we will rebuild
			handler.rebuild();
	}
	
	/**
	 * 获取编译后的字节码
	 * @return
	 */
	protected byte[] getCode() {
			return code;
	}
	
}
